class Computer():
    B = 1
    KB = 1024
    MB = 1024**2
    GB = 1024**3
    TB = 1024**4
    PB = 1024**5
    uniform_2_display = {  # 制式单位对应的简称和标准英文全称
        B: ("B", "Byte")
        , KB: ("KB", "Kilobyte")
        , MB: ("MB", "Megabyte")
        , GB: ("GB", "Gigabyte")
        , TB: ("TB", "Terabyte")
        , PB: ("PB", "Petabyte")
    }

    def __init__(self):
        raise NotImplementedError

    @staticmethod
    def convert_with_suffix(number, src_unit, des_unit = None, precise = 2, suffix_mode = "brief"):
        """
        将指定单位的数目转换为另一单位且带单位描述的字符串
        :param number:
        des_unit: 目标单位,为None时自动指定最接近的单位
        precise: 转换后保留的小数精度,默认为2位
        suffix_mode: 后缀模式(brief or full),比如是KB,还是Kilobytes
        :return:
        """
        if des_unit is None:
            uniforms = [Computer.B, Computer.KB, Computer.MB, Computer.GB, Computer.TB, Computer.PB]
            src_unit_cursor = uniforms.index(src_unit)
            number_i = number
            while src_unit_cursor < len(uniforms)-1:
                number_i //= 1024
                if number_i == 0:
                    break
                src_unit_cursor += 1
            des_unit = uniforms[src_unit_cursor]

        delta_unit = des_unit // src_unit # 最终单位的差量
        des_num = number / delta_unit
        des_num_str = "{0:.{1}f}".format(des_num, precise)
        if suffix_mode == "brief":
            return des_num_str + Computer.uniform_2_display[des_unit][0]
        elif suffix_mode == "full":
            return des_num_str + Computer.uniform_2_display[des_unit][1]

class Time():
    USec = 1
    MSec = 1000
    Sec = 1000**2
    Min = 60*1000**2
    Hour = 60**2*1000**2
    Day = 24*60**2*1000**2
    uniform_2_display = {
        USec: ("USec", "MicroSecond")
        , MSec: ("MSec", "MilliSecond")
        , Sec: ("Sec", "Second")
        , Min: ("Min", "Minute")
        , Hour: ("Hour", "Hour")
        , Day: ("Day", "Day")
    }

    def __init__(self):
        raise NotImplementedError

    @staticmethod
    def convert_with_suffix(number, src_unit, des_unit = None, precise = 2, suffix_mode = "brief"):
        """
        将指定单位的数目转换为另一单位且带单位描述的字符串
        :param number:
        des_unit: 目标单位,为None时自动指定最接近的单位
        precise: 转换后保留的小数精度,默认为2位
        suffix_mode: 后缀模式(brief or full),比如是Sec,还是Second
        :return:
        """
        if des_unit is None:
            uniforms = [Time.USec, Time.MSec, Time.Sec, Time.Min, Time.Hour, Time.Day]
            src_unit_cursor = uniforms.index(src_unit)
            number_i = number
            while src_unit_cursor < len(uniforms)-1:
                if src_unit_cursor == 0: # usec->msec
                    number_i //= 1000
                elif src_unit_cursor == 1:  # msec->sec
                    number_i //= 1000
                elif src_unit_cursor == 2: # sec->min
                    number_i //= 60
                elif src_unit_cursor == 3: # min->hour
                    number_i //= 60
                elif src_unit_cursor == 4: # hour->day
                    number_i //= 24
                if number_i == 0:
                    break
                src_unit_cursor += 1
            des_unit = uniforms[src_unit_cursor]
        delta_unit = des_unit // src_unit  # 最终单位的差量
        des_num = number / delta_unit
        des_num_str = "{0:.{1}f}".format(des_num, precise)
        if suffix_mode == "brief":
            return des_num_str + Time.uniform_2_display[des_unit][0]
        elif suffix_mode == "full":
            return des_num_str + Computer.uniform_2_display[des_unit][1]